﻿using System;
using System.Collections.Generic;
using System.Collections.ObjectModel;
using System.ComponentModel;
using System.Diagnostics;
using System.Linq;
using Moonwish.Core;
using Moonwish.Core.EntityCore;
using Moonwish.Foundation.DataEntity;
using Moonwish.Foundation.Interfaces;

namespace Moonwish.Foundation.ValueObjects
{
    /// <summary>
    /// 值对象分类ViewModel，by zhlin 2011-08-08
    /// </summary>
    public class ValueObjectClass : NotificationObject<ValueObjectClass>, IFoundationObject
    {
        private readonly V_FDT_ValueObjectClass _entity;
        private ValueObjectModel _model;
        private readonly ValueObjectCollection _valueObjects;
        internal readonly Dictionary<string, ValueObject> QuicklyValueObjects = new Dictionary<string, ValueObject>();

        public const string FiledStatus = "ValueObjectClass.Status";

        public ValueObjectClass()
        {
            _entity = new V_FDT_ValueObjectClass
                          {
                              ValueObjectClassId = Guid.NewGuid().ToString(),
                              DataStatus = DataStatus.New.ToString()
                          };
            _valueObjects = new ValueObjectCollection(this); 
        }

        internal ValueObjectClass(V_FDT_ValueObjectClass entity)
        {
            _entity = entity;
            _valueObjects = new ValueObjectCollection(this);
        }

        internal ValueObjectModel Model
        {
            get { return _model; }
            set
            {
                Debug.Assert(value != null);
                if (_model != value)
                {
                    _model = _valueObjects.Model = value;
                    foreach (var item in _valueObjects)
                    {
                        item.Model = _model;
                    }
                }
            }
        }

        internal V_FDT_ValueObjectClass Entity
        {
            get
            {
                return _entity;
            }
        }

        public ValueObjectCollection ValueObjects
        {
            get
            {
                return _valueObjects;
            }
        }

        public string Id
        {
            get
            {
                return _entity.ValueObjectClassId;
            }
        }

        public string Name
        {
            get
            {
                return _entity.Name;
            }
            set
            {
                if (_entity.Name != value)
                {
                    _entity.Name = value;
                    ClearError("Name");
                    RaisePropertyChanged("Name");
                }
            }
        }

        public string Code
        {
            get
            {
                return _entity.Code;
            }
            set
            {
                if (_entity.Code != value)
                {
                    _entity.Code = value;
                    ClearError("Code");
                    RaisePropertyChanged("Code");
                }
            }
        }

        public int? OrderNo
        {
            get
            {
                return _entity.OrderNo;
            }
            set
            {
                if (_entity.OrderNo != value)
                {
                    _entity.OrderNo = value;
                    ClearError("OrderNo");
                    RaisePropertyChanged("OrderNo");
                }
            }
        }

        public DataStatus DataStatus
        {
            get
            {
                return (DataStatus)Enum.Parse(typeof(DataStatus), _entity.DataStatus, true);
            }
            set
            {
                if (value > DataStatus)
                {
                    var oldState = _entity.ChangeTracker.State;
                    _entity.DataStatus = value.ToString();
                    _entity.ChangeTracker.State = oldState;
                    RaisePropertyChanged("DataStatus");
                    RaisePropertyChanged("StatusName");
                }
                else
                    throw new InvalidOperationException(string.Format("系统不允许将状态从“{0}”设置为“{1}”。", DataStatus, value));
            }
        }

        /// <summary>
        /// 数据状态名称。
        /// </summary>
        public string StatusName
        {
            get
            {
                switch (DataStatus)
                {
                    case DataStatus.New :
                        return "新建";
                    case DataStatus.Released:
                        return "发布";
                    case DataStatus.Disabled:
                        return "作废";
                    default:
                        return "未知";
                }
            }
        }

        public string Remark
        {
            get { return _entity.Remark; }
            set
            {
                if (value != _entity.Remark)
                {
                    Entity.Remark = value;
                    ClearError("Remark");
                    RaisePropertyChanged("Remark");
                }
            }
        }

        /// <summary>
        /// 数据验证。
        /// </summary>
        /// <returns></returns>
        public override bool Validate()
        {
            bool isValid = true;
            ClearAllErrors();
            if (String.IsNullOrEmpty(Name))
            {
                isValid = false;

                SetError("Name", "名称不能为空。");
            }
            if (isValid && Name.Length > 50)
            {
                isValid = false;
                SetError("Name", "名称不能大于50字。");
            }

            if (isValid && !string.IsNullOrEmpty(Code) && Code.Length > 10)
            {
                isValid = false;
                SetError("Code", "编码不能大于10字。");
            }
            if (isValid && !string.IsNullOrEmpty(Remark) && Remark.Length > 50)
            {
                isValid = false;
                SetError("Remark", "描述不能大于50字。");
            }
            return isValid;
        }

        public override void AcceptChanges()
        {
            _entity.ChangeTracker.AcceptChanges();
        }

        /// <summary>
        /// 克隆实体。
        /// </summary>
        /// <returns></returns>
        public override ValueObjectClass Clone()
        {
            var cloneObj = new ValueObjectClass
            {
                Code = Code,
                Name = Name,
                OrderNo = OrderNo,
                Remark = Remark
            };

            foreach (var item in _valueObjects)
            {
                cloneObj.ValueObjects.BaseAdd(item.Clone());
            }
            return cloneObj;
        }

        /// <summary>
        /// 覆盖数据。
        /// </summary>
        /// <param name="newItem"></param>
        public override void Override(ValueObjectClass newItem)
        {
            Code = newItem.Code;
            Name = newItem.Name;
            OrderNo = newItem.OrderNo;
            Remark = newItem.Remark;
        }

        /// <summary>
        /// 发布数据完成事件。
        /// </summary>
        public event AsyncCompletedEventHandler PublishCompleted;
        /// <summary>
        /// 发布数据。
        /// </summary>
        public void PublishAsync()
        {
            if (DataStatus != DataStatus.New)
            {
                throw new InvalidOperationException(string.Format("值对象分类“{0}”已发布或已作废，不能再次发布。", Name));
            }
            if (_entity.ChangeTracker.State != ObjectState.Unchanged)
            {
                throw new InvalidOperationException(string.Format("值对象分类“{0}”尚未被保存到数据库，不能被发布。", Name));
            }
            Model.ValueObjectProxy.PublishValueObjectClassCompleted += PublishValueObjectClassCompleted;
            Model.ValueObjectProxy.PublishValueObjectClassAsync(new ObservableCollection<string> { Id }, "Default", new AsyncEventStateObject { Model = Model, Data = this });
        }

        /// <summary>
        /// 发布多个数据完成事件。
        /// </summary>
        public static event AsyncCompletedEventHandler PublishMoreCompleted;

        /// <summary>
        /// 发布多个。
        /// </summary>
        /// <param name="items"></param>
        /// <param name="model"></param>
        public static void PublishMoreAsync(List<ValueObjectClass> items, ValueObjectModel model)
        {
            var newCount = items.Count(obj => obj.DataStatus == DataStatus.New);
            if (newCount != items.Count)
            {
                throw new InvalidOperationException("值对象集合中有已发布或已作废的数据，无法发布。");
            }
            if (items.Count(obj => obj.Entity.ChangeTracker.State != ObjectState.Unchanged) > 0)
            {
                throw new InvalidOperationException("值对象集合中有尚未被保存到数据库，不能被发布。");
            }
            var ids = new ObservableCollection<string>();
            foreach (var id in items.Select(obj => obj.Id))
            {
                ids.Add(id);
            }
            model.ValueObjectProxy.PublishValueObjectClassCompleted += PublishValueObjectClassCompleted;
            model.ValueObjectProxy.PublishValueObjectClassAsync(ids, "Default", new AsyncEventStateObject { Model = model, Data = items });
        }
        
        /// <summary>
        /// 发布完成事件。
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        static void PublishValueObjectClassCompleted(object sender, AsyncCompletedEventArgs e)
        {
            
            var stateObject = (AsyncEventStateObject)e.UserState;

            var model = (ValueObjectModel)stateObject.Model;

            try
            {
                if (e.Error != null) return;

                // 如果是单个发布
                var target = stateObject.Data as ValueObjectClass;
                if (target != null)
                {
                    target.DataStatus = DataStatus.Released;

                    // 发布子数据项。
                    foreach (var item in target.ValueObjects)
                    {
                        if (item.DataStatus == DataStatus.New)
                        {
                            item.DataStatus = DataStatus.Released;
                        }
                    }
                    var handler = target.PublishCompleted;

                    if (handler != null)
                    {
                        handler(target, e);
                    }
                }

                // 如果是多个发布
                var items = stateObject.Data as List<ValueObjectClass>;
                if (items != null)
                {
                    foreach (var valueObjectClass in items)
                    {
                        valueObjectClass.DataStatus = DataStatus.Released;

                        // 发布子数据项。
                        foreach (var item in valueObjectClass.ValueObjects)
                        {
                            if (item.DataStatus == DataStatus.New)
                            {
                                item.DataStatus = DataStatus.Released;
                            }
                        }
                    }
                    var handler = PublishMoreCompleted;

                    if (handler != null)
                    {
                        handler(null, e);
                    }
                }
            }
            finally
            {
                model.ValueObjectProxy.PublishValueObjectClassCompleted -= PublishValueObjectClassCompleted;
            }
        }

        /// <summary>
        /// 作废完成事件。
        /// </summary>
        public event AsyncCompletedEventHandler DisableCompleted;

        /// <summary>
        /// 作废数据。
        /// </summary>
        public void DisableAsync()
        {
            if (DataStatus != DataStatus.Released)
            {
                throw new InvalidOperationException(string.Format("值对象分类“{0}”不是已发布的数据，不能作废。", Name));
            }
            if (_entity.ChangeTracker.State != ObjectState.Unchanged)
            {
                throw new InvalidOperationException(string.Format("值对象分类“{0}”尚未被保存到数据库，不能被作废。", Name));
            }
            _model.ValueObjectProxy.DisableValueObjectClassCompleted += DisableValueObjectClassCompleted;
            _model.ValueObjectProxy.DisableValueObjectClassAsync(new ObservableCollection<string> { Id }, "Default", new AsyncEventStateObject { Model = Model, Data = this });
        }

        /// <summary>
        /// 发布多个数据完成事件。
        /// </summary>
        public static event AsyncCompletedEventHandler DisableMoreCompleted;
        /// <summary>
        /// 发布多个。
        /// </summary>
        /// <param name="items"></param>
        /// <param name="model"></param>
        public static void DisableMoreAsync(List<ValueObject> items, ValueObjectModel model)
        {
            var newCount = items.Count(obj => obj.DataStatus == DataStatus.Released);
            if (newCount != items.Count)
            {
                throw new InvalidOperationException("值对象分类集合中有未发布的数据，无法作废。");
            }
            if (items.Count(obj => obj.Entity.ChangeTracker.State != ObjectState.Unchanged) > 0)
            {
                throw new InvalidOperationException("值对象分类集合中有尚未被保存到数据库，不能被发布。");
            }
            var ids = new ObservableCollection<string>();
            foreach (var id in items.Select(obj => obj.Id))
            {
                ids.Add(id);
            }
            model.ValueObjectProxy.DisableValueObjectClassCompleted += DisableValueObjectClassCompleted;
            model.ValueObjectProxy.DisableValueObjectClassAsync(ids, "Default", new AsyncEventStateObject { Model = model, Data = items });
        }

        /// <summary>
        /// 作废完成事件。
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        static void DisableValueObjectClassCompleted(object sender, AsyncCompletedEventArgs e)
        {
            var stateObject = (AsyncEventStateObject)e.UserState;

            var model = (ValueObjectModel)stateObject.Model;

            try
            {
                if (e.Error != null) return;

                // 如果是单个作废
                var target = stateObject.Data as ValueObjectClass;
                if (target != null)
                {
                    target.DataStatus = DataStatus.Disabled;

                    // 作废子数据项。
                    foreach (var item in target.ValueObjects)
                    {
                        if (item.DataStatus == DataStatus.Released)
                        {
                            item.DataStatus = DataStatus.Disabled;
                        }
                    }
                    var handler = target.DisableCompleted;

                    if (handler != null)
                    {
                        handler(target, e);
                    }
                }

                // 如果是多个作废
                var items = stateObject.Data as List<ValueObjectClass>;
                if (items != null)
                {
                    foreach (var valueObjectClass in items)
                    {
                        valueObjectClass.DataStatus = DataStatus.Released;

                        // 作废子数据项。
                        foreach (var item in valueObjectClass.ValueObjects)
                        {
                            if (item.DataStatus == DataStatus.Released)
                            {
                                item.DataStatus = DataStatus.Disabled;
                            }
                        }
                    }
                    var handler = DisableMoreCompleted;

                    if (handler != null)
                    {
                        handler(null, e);
                    }
                }
            }
            finally
            {
                model.ValueObjectProxy.DisableValueObjectClassCompleted -= DisableValueObjectClassCompleted;
            }
        }

        /// <summary>
        /// 保存完成事件。
        /// </summary>
        public event AsyncCompletedEventHandler SaveChangedCompleted;
       /// <summary>
       /// 保存修改事件。
       /// </summary>
        public void SaveChangedAsync()
        {
            if (Entity.ChangeTracker.State != ObjectState.Modified)
            {
                throw new InvalidOperationException(string.Format("值对象分类“{0}”数据未作任何修改，无法保存。", Name));
            }
            Model.ValueObjectProxy.SaveValueObjectClassCompleted += SaveValueObjectClassCompleted;
            Model.ValueObjectProxy.SaveValueObjectClassAsync(new ObservableCollection<V_FDT_ValueObjectClass> { Entity }, "Default");
        }

        /// <summary>
        /// 保存完成事件。
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        void SaveValueObjectClassCompleted(object sender, AsyncCompletedEventArgs e)
        {
            try
            {
                if (e.Error != null) return;

                AcceptChanges();

            }
            finally
            {
                Model.ValueObjectProxy.SaveValueObjectClassCompleted -= SaveValueObjectClassCompleted;

                var handler = SaveChangedCompleted;

                if (handler != null)
                {
                    handler(this, e);
                }
            }
        }
    }
}
